package hu.gar.web.user;

import hu.gar.common.service.UserService;
import hu.gar.vo.RoleVO;
import hu.gar.vo.UserVO;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

public class LazyUserDataModel extends LazyDataModel<UserDisplayVO> {

	private List<UserDisplayVO> datasource;
	private UserService userService;

	public LazyUserDataModel(UserService userService) {
		this.userService = userService;

	}

	@Override
	public UserDisplayVO getRowData(String rowKey) {
		for (UserDisplayVO UserDisplayVO : datasource) {
			if (UserDisplayVO.getId().toString().equals(rowKey))
				return UserDisplayVO;
		}

		return null;
	}

	@Override
	public Object getRowKey(UserDisplayVO UserDisplayVO) {
		return UserDisplayVO.getId();
	}

	@Override
	public List<UserDisplayVO> load(int first, int pageSize, String sortField,
			SortOrder sortOrder, Map<String, Object> filters) {
		datasource = userToUserDisplayVOs(userService.getAllUser());

		for (UserDisplayVO displayVO : datasource) {
			List<RoleVO> roleVOs = userService.getRolesByUserId(displayVO
					.getId());
			String roles = "";
			int index = 0;
			for (RoleVO roleVO : roleVOs) {
				index++;
				roles += roleVO.getRole();
				if (index != roleVOs.size()) {
					roles += ", ";
				}

			}
			displayVO.setRoles(roles);
		}
		List<UserDisplayVO> data = new ArrayList<UserDisplayVO>();

		// filter
		for (UserDisplayVO organizationDisplayVO : datasource) {
			boolean match = true;

			if (filters != null) {
				for (Iterator<String> it = filters.keySet().iterator(); it
						.hasNext();) {
					try {
						String filterProperty = it.next();
						Object filterValue = filters.get(filterProperty);
						String field = filterProperty;
						field = field.substring(0, 1).toUpperCase()
								+ field.substring(1);
						Method method = UserDisplayVO.class.getMethod("get"
								+ field, null);

						String fieldValue = String.valueOf(method
								.invoke(organizationDisplayVO));

						if (filterValue == null
								|| fieldValue.toLowerCase().startsWith(
										filterValue.toString().toLowerCase())) {
							match = true;
						} else {
							match = false;
							break;
						}
					} catch (Exception e) {
						match = false;
					}
				}
			}

			if (match) {
				data.add(organizationDisplayVO);
			}
		}

		// sort
		if (sortField != null) {
			Collections.sort(data, new LazyUserSorter(sortField, sortOrder));
		}

		// rowCount
		int dataSize = data.size();
		this.setRowCount(dataSize);
		// paginate
		if (dataSize > pageSize) {
			try {
				return data.subList(first, first + pageSize);
			} catch (IndexOutOfBoundsException e) {
				return data.subList(first, first + (dataSize % pageSize));
			}
		} else {
			return data;
		}
	}

	public static UserDisplayVO userToUserDisplayVO(UserVO userVO) {
		UserDisplayVO displayVO = new UserDisplayVO();
		displayVO.setUsername(userVO.getUsername());
		displayVO.setId(userVO.getId());
		return displayVO;

	}

	public static UserVO userDisplayVOToUserVO(UserDisplayVO userDisplayVO) {
		UserVO userVO = new UserVO();
		userVO.setUsername(userDisplayVO.getUsername());
		userVO.setId(userDisplayVO.getId());
		return userVO;
	}

	public static List<UserDisplayVO> userToUserDisplayVOs(List<UserVO> userVO) {
		List<UserDisplayVO> displayVOs = new ArrayList<UserDisplayVO>();
		for (UserVO user : userVO) {
			displayVOs.add(userToUserDisplayVO(user));
		}
		return displayVOs;
	}

	public static List<UserVO> userDisplayVOToUserVOs(List<UserDisplayVO> userVO) {
		List<UserVO> userVOs = new ArrayList<UserVO>();
		for (UserDisplayVO user : userVO) {
			userVOs.add(userDisplayVOToUserVO(user));
		}
		return userVOs;
	}
}
